class THhMqClientV10 {
    constructor(){
        this.config={
            appId:"vSport" , 
            apiUrl:"https://wss.hhdata.cn:20036",
            mq:{                
                host:"gmggf8g.mqtt.iot.bj.baidubce.com",
                port:443,
                uid:"gmggf8g/peer",
                pwd:"a52bwKg22dCAuQzB"
            }, 
            kmsPeerOptions :{
                configuration: {
                    "iceServers": [ 
                        {
                            urls: "stun:223.68.161.139:3478"
                            //urls: "stun:223.112.194.253:40016"
                        },
                        {
                            urls: ["turn:223.68.161.139:3478"  ],
                            //urls: ["turn:223.112.194.253:40016"  ],
                            username: "kurento",
                            credential: "kurento"
                        }
                    ]
                },
                mediaConstraints: {
                    audio: true,
                    //video: {width: {exact: 1280}, height: {exact: 720}},
                    video: {
                        width: { min: 1280, ideal: 1280, max: 1920 },
                        height: { min: 720, ideal: 720 , max: 1080}
                    }
                }
            },
            kmsPeerTypes : {
                s: kurentoUtils.WebRtcPeer.WebRtcPeerSendonly,
                r: kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly,
                sr: kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv
            } 
        }
        this.peers = {};
        this.reqQueue ={};
    }
    log( logData ){
        console.log(logData);
    }
    cb( callback , p0,p1,p2  ){
        var me = this;
        try{
            if( callback){
                callback(p0,p1,p2);
            }
        }
        catch(er){
            console.log(er); 
        };
    }
    callApi( category , module , ac , ps ){
        var me = this;
        return new Promise( (success , faild)=>{
            try{
                var apiPath= [me.config.baseUrl , category , module , ac].join("/");
                axios.post(apiPath , ps).then((res)=>{
                    if( res){
                        success(res.data);
                    }
                    else{
                        success(null);
                    }
                });
            }
            catch(er){
                console.log(er);
                success();
            }
        });
    }
    query( key , ps  ){
        var me = this;
        return new Promise( (success , faild)=>{
            try{
                var postPs={
                    appId: me.config.appId ,
                    key:key ,
                    psJson: JSON.stringify( ps)
                }
                me.callApi("common" , "mysqldb" , "query" , postPs ).then((res)=>{
                    if( res && res.data && res.data.result){
                        success(res.data.result);
                    }
                    else{
                        success();
                    }
                });
            }
            catch(er){
                console.log(er);
                success();
            }
        });
    }
    openMq( clientId , connectEvent , dicConnectEvent , receiveMsgEvent ){
        var me = this;
        return new Promise((success , faild)=>{
            try{
                var client = null; 
                var willTopic = 'hh/'+me.config.appId+"/svr";
                var willMsg = {
                    msgId:"offline" ,
                    msgBody:{
                        clientId: clientId 
                    }
                }
                var onConnect = function () {
                    var topic ='hh/'+ me.config.appId+"/"+clientId+"/#"
                    client.subscribe(topic);
                    me.cb(connectEvent , client);
                    success(client);
                };
                var onDisConnect = function () {
                    me.cb(dicConnectEvent);                    
                };
                var onRecMsg = function (msg) {
                    try{
                        var msgData = JSON.parse(msg.MsgContent); 
                        if( msgData.reqId && msgData.reqId!=null){
                            if( me.reqQueue && me.reqQueue[msgData.reqId] ){
                                var reqInfo = me.reqQueue[msgData.reqId];
                                reqInfo.respHandler( msgData.reqId , msgData);
                            }
                        }
                        else if (me.handlers && me.handlers[msg.id]){
                            var handler = me.handlers[msgId];
                            me.cb( handler , msgData);
                        }
                        else{
                            me.cb( receiveMsgEvent , msgData);
                        }
                    }
                    catch(eer){
                        me.log(eer)
                    }
                }
                client = createMqClient(
                    me.config.mq.host,
                    me.config.mq.port,
                    me.config.mq.uid,
                    me.config.mq.pwd,
                    clientId,
                    "",
                    1, willTopic, willMsg,
                    onConnect, onDisConnect, onRecMsg
                );                
                client.sendMsg= function( topic , msgId ,  msgBody){
                    try{
                        var content = JSON.stringify({
                            id: msgId ,
                            clientId: client.clientId ,
                            body: msgBody
                        })
                        client.publish(topic , content);
                    }
                    catch(eer){
                        me.log(eer);
                        su();
                    }
                }               
                client.sendSyncMsg= function( topic , msgId ,  msgBody , timeout){
                    return new Promise((su , fa)=>{
                        try{
                            var reqId = ['rid' , ( new Date()).getTime() , parseInt(1000*Math.random())].join('');
                            me.requestInfo[reqId]={
                                reqId:reqId,
                                timer: null
                            }
                            client.sendMsg(topic , msgId ,  msgBody);
                            var respHandler = function( reqId , respMsg ){
                                try{
                                    if( me.requestInfo[reqId] && me.requestInfo[reqId].timer){
                                        window.clearTimeout(me.requestInfo[reqId].timer);
                                    }
                                    su(respMsg);
                                }
                                catch(eer){
                                    me.log(eer);
                                    su(null);
                                }
                            }
                            me.requestInfo[reqId].respHandler = respHandler;
                            me.requestInfo[reqId].timer = window.setTimeout( respHandler , timeout , reqId , null);
                        }
                        catch(eer){
                            me.log(eer);
                            su();
                        }
                    });
                }                             
                client.registHandler= function( handlerId , handler ){
                    try{ 
                        if( !client.handlers){
                            client.handlers = {}
                        }
                        client.handlers[handlerId] = handler;
                    }
                    catch(eer){
                        me.log(eer);
                        su();
                    }
                }

                var opts = client.connectionOptions;
                client.connect(opts);
            }
            catch(er){
                me.log(er);
            }
        })
    }
    loadChannel( mqClient ,  chId ){
        var me = this;
        return new Promise((success , faild)=>{
            try{ 
                var topic = 'hh/'+me.config.appId+"/svr";
                var msgBody ={
                    chId: chId
                };
                mqClient.sendSyncMsg(topic , "acLoadChannel", msgBody , 5000).then(res=>{
                    success(res);
                });
            }
            catch(er){
                me.log(er);
            }
        })
    }
    loadPlayer( mqClient , chId , playerCode , srcUrl ){
        var me = this;
        return new Promise((success , faild)=>{
            try{ 
                var topic = 'hh/'+me.config.appId+"/svr";
                var msgBody ={
                    chId: chId,
                    endCode: playerCode ,
                    clientId: mqClient.clientId ,
                    url:srcUrl
                };
                mqClient.sendSyncMsg(topic , "acLoadPlayer", msgBody , 5000).then(res=>{
                    success(res);
                });
            }
            catch(er){
                me.log(er);
            }
        })
    }
    connectMedia( mqClient , srcId , targetId , mediaType ){
        var me = this;
        return new Promise((success , faild)=>{
            try{ 
                var topic = 'hh/'+me.config.appId+"/svr";
                var msgBody ={
                    srcId: srcId,
                    targetId: targetId ,
                    mediaType: mediaType
                };
                mqClient.sendSyncMsg(topic , "acConnectMedia", msgBody , 5000).then(res=>{
                    success(res);
                });
            }
            catch(er){
                me.log(er);
            }
        })
    }
    createPeer( mqClient , chId , endCode , peerType , lv , rv){
        var me = this;
        return new Promise((success , faild)=>{
            try{ 
                var sessionInfo = null;
                var peer = null; 
                
                if( !mqClient.kmsSession){
                    mqClient.kmsSession = {};
                }
                if(!mqClient.handlers || !mqClient.handlers['endCandidate']){
                    mqClient.registHandler('endCandidate' , function(msg){
                        var session = mqClient.kmsSession[msg.body.sessionId];
                        var flag = session && session.peer!=null;
                        var candidate = msg.body.candidate;
                        if( flag){
                            peer.addIceCandidate(candidate);
                        }
                        else{
                            if(!mqClient.sessionCandidateBuf ){
                                mqClient.sessionCandidateBuf={};
                            }
                            if(!mqClient.sessionCandidateBuf[session.sessionId] ){
                                mqClient.sessionCandidateBuf[session.sessionId]=[];
                            }
                            mqClient.sessionCandidateBuf[session.sessionId].push(candidate);
                        }
                    })
                }
                var requestSession = function( onRequest){                        
                    var topic = 'hh/'+me.config.appId+"/svr";
                    var msgBody ={
                        chId: chId,
                        endCode: endCode 
                    };
                    mqClient.sendSyncMsg(topic , "acCreateSession", msgBody , 5000).then(res=>{
                        sessionInfo = res.body;
                        mqClient.kmsSession[sessionInfo.sessionId] = sessionInfo;
                        onRequest();
                    });
                }
                var createLocalPeer = function( onCreate){
                    var factory = me.config.kmsPeerTypes[peer];
                    var opts = JSON.parse(JSON.stringify(me.config.kmsPeerOptions));
                    if( peerType=='s' ){
                        opts.localVideo = lv;
                    }
                    else if( peerType=='r' ){
                        opts.remoteVideo = rv;
                    }
                    else if( peerType=='sr' ){
                        opts.localVideo = lv;
                        opts.remoteVideo = rv;
                    }
                    peer = factory(opts , function(erP){
                        var flag = 
                            mqClient.sessionCandidateBuf && 
                            mqClient.sessionCandidateBuf[session.sessionId] &&
                            mqClient.sessionCandidateBuf[session.sessionId].length>0;
                        if( flag){
                            while(mqClient.sessionCandidateBuf[session.sessionId].length>0){
                                var candidate = mqClient.sessionCandidateBuf[session.sessionId].shift();
                                peer.addIceCandidate(candidate);
                            }
                        }
                        peer.mqClient = mqClient;
                        peer.sessionId = sessionInfo.sessionId;
                        sessionInfo.peer = peer;
                        peer.on('icecandidate', function (candidate) {
                            var iceCandidate = kurentoClient.register.complexTypes.IceCandidate(candidate); 
                            console.log('candidate p->w')
                            var candaditeMsg ={
                                sessionId: sessionInfo.sessionId ,
                                cnadadite : iceCandidate
                            }
                            mqClient.sendMsg ( topic , "peCandidate" , candaditeMsg);
                        });
                        onCreate();
                    });
                }
                var processAnswer = function( onProcess){
                    peer.generateOffer(function (errorPeerGenerateOffer, sdpOffer) {                    
                        var topic = 'hh/'+me.config.appId+"/svr";
                        var msgBody ={ 
                            sessionId: sessionInfo.sessionId ,
                            sdpOffer : sdpOffer
                        };
                        mqClient.sendSyncMsg(topic , "acEndOffer", msgBody , 5000).then(res=>{
                            var answer = res.body.sdpAnswer;
                            peer.processAnswer(answer, function(erAnswer){
                                onProcess();
                            });
                        }); 
                    });
                }
                requestSession( function(){
                    createLocalPeer( function(){
                        processAnswer(function(){
                            success( peer );
                        })
                    })
                })
            }
            catch(er){
                me.log(er);
            }
        })
    }
    static getDevice( ){ 
        var res ={};
        return new Promise( (success , faild)=>{
            try{
                navigator.mediaDevices.enumerateDevices().then(function (devs) {
                    try {
                        for (var i = 0; i < devs.length; i++) {
                            var item = devs[i];
                            if (!res[item.kind]) {
                                res[item.kind] = []
                            }
                            res[item.kind].push(item);
                        }
                    }
                    catch (er) {
                        console.log(er)
                    }
                    success(res);
                }).catch(function () {
                    success(res);
                });
            }
            catch(er){
                console.log(er);
                success(res);
            }
        });
    }
    static setHD( obj ){ 
        return new Promise( (success , faild)=>{
            try{
                obj.setMaxVideoRecvBandwidth(6000).then(()=>{
                    return obj.setMaxVideoRecvBandwidth(6000);
                }).then(()=>{
                    return obj.setMaxVideoSendBandwidth(6000);
                }).then(()=>{
                    return obj.setMinVideoRecvBandwidth(3000);
                }).then(()=>{
                    return obj.setMinVideoSendBandwidth(3000);
                }).then(()=>{
                    success( );
                });
            }
            catch(er){
                console.log(er);
                success( );
            }
        });
    }
    static setCamera( peer ,  cameraDeviceId ){ 
        return new Promise( (success , faild)=>{
            try{
                if (window.rtcVideoStream) {
                    window.rtcVideoStream.getTracks().forEach(track => {
                        if( track.kind=="video") { 
                            track.stop();
                        }
                    });
                }
                window.cam = window.cam ? window.cam :"user";
                window.cam = window.cam =="user" ? "environment":"user";
                var constraints = {
                    video: {
                        deviceId : cameraDeviceId ,  
                        height:{exact:720} , 
                        width:{exact:1280}
                    }
                };
                var sender= null; 
                
                navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { 
                    try {
                        window.rtcVideoStream = stream;
                        peer.localVideo.srcObject = stream;
                        /*
                        var peerConnection = peer.peerConnection ;
                        peerConnection.removeStream(peerConnection.getLocalStreams()[0]);
                        peerConnection.addLocalStream(stream);
                        */

                        let videoTrack = stream.getVideoTracks()[0];
                        sender = peer.peerConnection.getSenders().find(function (s) {
                            return s.track.kind == videoTrack.kind;
                        });
                        sender.track.stop();
                        sender.replaceTrack(videoTrack);
                        success();
                    }
                    catch (eSet) {
                        success();
                    }
                }).catch(function (erSet) { 
                    success();
                });
            }
            catch(er){ 
                console.log(er);
                success( );
            }
        });
    }
    static switchCamera( peer ){ 
        return new Promise( (success , faild)=>{
            try{
                var action  = function(){
                    var ids =[
                        peer.devices.videoinput[0].deviceId ,
                        peer.devices.videoinput[peer.devices.videoinput.length-1].deviceId
                    ]; 
                    var cameraId = (
                        peer.cameraId  &&
                        peer.cameraId !=null &&
                        peer.cameraId.length>0 )?peer.cameraId : "";
                    cameraId = cameraId == ids[0]?ids[1]:ids[0];
                    TCommClient.setCamera(peer , cameraId ).then(()=>{
                        peer.cameraId = cameraId;
                        success();
                    })
                }
                
                TCommClient.getDevice().then(res=>{
                    peer.devices = res;
                    action();
                })
            }
            catch(er){
                console.log(er);
                success( );
            }
        });
    }
    static shareScreen( peer , width , height ){ 
        return new Promise( (success , faild)=>{
            try{
                var wWidth = width?width : $(window).width();
                var wHeight = height?height: $(window).height();
                var screenConstraints = {video: {width: {max:wWidth}, height: {max: wHeight}}, audio: true};
                var sender= null;
                if (navigator.mediaDevices.getDisplayMedia) {
                    navigator.mediaDevices.getDisplayMedia(screenConstraints).then(
                        function (stream) {
                            let videoTrack = stream.getVideoTracks()[0];
                            peer.localVideo.srcObject = stream;
                            sender = peer.peerConnection.getSenders().find(function (s) {
                                return s.track.kind == videoTrack.kind;
                            });
                            sender.track.stop();
                            sender.replaceTrack(videoTrack);
                            success();
                        }
                    )
                }
                else{
                    success();
                }
            }
            catch(er){
                console.log(er);
                success( );
            }
        });
    }
    static fullScreen( peer  ){ 
        return new Promise( (success , faild)=>{
            try{
                var element = peer.remoteVideo;
                if (element.requestFullscreen) {
                    element.requestFullscreen();
                } else if (element.msRequestFullscreen) {
                    element.msRequestFullscreen();
                } else if (element.mozRequestFullScreen) {
                    element.mozRequestFullScreen();
                } else if (element.webkitRequestFullscreen) {
                    element.webkitRequestFullscreen();
                }
            }
            catch(er){
                console.log(er);
                success( );
            }
        });
    }
}

var hhClient = new THhMqClientV10();
